<template>
  <view class="container">
    <view class="message_model" id="message_model" ref="message_model">
      <!-- 问答方式 -->
      <view class="qaType_text" @click="qaTypeFn">
        <text :class="checked ? 'select' : ''">生成式</text>
        <text :class="!checked ? 'select' : ''">知识库</text>
      </view>

      <scroll-view ref="scrollView" :scroll-top="scrollTop" scroll-y="true">
        <!-- 聊天记录 -->
        <template v-if="sessionId" v-for="(item, index) in messageList">
          <view class="message" :style="item.id === 1001 ? 'flex-direction:row-reverse' : ''">
            <image class="image" v-if="item.id === 1001" :src="item.photo"></image>
            <image class="image" v-else :src="item.chat_type == 'raw' ? '../../static/images/raw.svg' : '../../static/images/rag.svg'"></image>
            <view class="message_content">
              <!-- <text class="name">{{ item.name }}</text> -->

              <uaMarkdown :source="item.content" v-if="item.id !== 1001" :showLine="false" class="uaMarkdownClass"></uaMarkdown>
              <text v-else class="content self">{{ item.content }}</text>
              <view class="fileList" v-if="item.source_list && item.source_list.length !== 0">
                <view class="title">关联资料：</view>
                <view class="view_list">
                  <view class="file" v-for="(i, index) in item.source_list" @click="fileInfoFn(i)" :key="index"> 文件名称:{{ i.file_detail.name + i.file_detail.ext }}</view>
                </view>
              </view>
            </view>
          </view>
        </template>
      </scroll-view>
    </view>
    <!-- 发送框 -->
    <view class="sendMessage">
      <u--textarea class="textarea" maxlength="500" autoHeight v-model="val" placeholder="请输入内容"></u--textarea>
      <!-- <u-button class="btn" text="发送" @click="sendFn"></u-button> -->
      <image class="btn" @click="sendFn" src="../../static/images/sendBtn.svg"></image>
    </view>
    <u-toast ref="uToast"></u-toast>
  </view>
</template>

<script>
import uaMarkdown from "../../components/ua2-markdown/ua-markdown";
export default {
  data() {
    return {
      scrollTop: 0,
      fileDialog: false,
      fileText: "",
      val: "",
      checked: true,
      sessionId: "",
      sessionList: [],
      messageList: [],
      isEND: false,
      qaStatus : true,
      str_list:''
    };
  },
  components: {
    uaMarkdown,
  },
  onLoad(options) {
    this.sessionId = options.sessionId;
    this.getSession();
  },
  mounted() {},
  computed: {},
  watch: {},
  methods: {
    // 获取会话列表
    getSession() {
      let that = this;
      this.$request({
        url: "/knowledgeQa/get",
        method: "GET",
      }).then(({ data }) => {
        console.log(data, "fffff");
        this.sessionList = data.session;

        const result = this.sessionList.find((item) => item.id == this.sessionId);
        if (result) {
          this.messageList = result.message;
        }
        that.scrollBottom();
      });
    },
    // 保存会话
    sessionStart(item) {
      this.$request({
        url: "/knowledgeQa/add",
        method: "post",
        data: item,
      }).then(({ data }) => {
        console.log(data, "fffff");
      });
    },
    dateFn() {
      const currentDate = new Date();

      const date = `${currentDate.getFullYear()}-${String(currentDate.getMonth() + 1).padStart(2, "0")}-${String(currentDate.getDate()).padStart(2, "0")} ${String(currentDate.getHours()).padStart(2, "0")}:${String(currentDate.getMinutes()).padStart(2, "0")}:${String(currentDate.getSeconds()).padStart(2, "0")}`;
      console.log("date", date);
      return date;
    },
    fileInfoFn(item) {
      console.log(item);
      const datainfo = {
        ...item.file_detail,
        ext: {
          items: item.items,
        },
      };
      const search = true;
      // 指导书需要跳转的地方
      if (item.file_detail.extra.file_category === "D") {
        uni.navigateTo({
          url: `/pages/guideBookPreview?info=` + encodeURIComponent(JSON.stringify(datainfo)) + `&search=` + search,
        });
      } else if (["E","F"].includes(item.file_detail.extra.file_category)) {
        uni.navigateTo({
          url: `/pages/player?info=` + encodeURIComponent(JSON.stringify(datainfo)) + `&search=` + search,
        });
      } else if (item.file_detail.extra.file_category === "B") {
        uni.navigateTo({
          url: `/pages/page2Preview?info=` + encodeURIComponent(JSON.stringify(datainfo)) + `&search=` + search,
        });
      } else if (item.file_detail.extra.file_category === "C") {
        uni.navigateTo({
          url: `/pages/tablePreview?info=` + encodeURIComponent(JSON.stringify(datainfo)) + `&search=` + search,
        });
      } else {
        uni.navigateTo({
          url: `/pages/page1Preview?info=` + encodeURIComponent(JSON.stringify(datainfo)) + `&search=` + search,
        });
      }
    },
    // 问询
    // qaFn(value) {
    //   let that = this;
    //   let source_list = "";
    //   const result = that.sessionList.find((S) => S.id == that.sessionId);
    //   fetch(`${uni.$config.baseUrl}/kms-core-svc/qa`, {
    //     method: "POST",
    //     headers: {
    //       "Content-Type": "application/json",
    //       "token":uni.getStorageSync("token")
    //     },
    //     body: JSON.stringify({
    //       user_input: value,
    //       chat_type: this.checked ? "raw" : "rag",
    //       sessionId: this.sessionId,
    //       history: result.message,
    //     }),
    //   }).then((response) => {
    //       console.log("看看这个是啥",response)
    //       // return
    //       // 检查响应是否为流式响应
    //       if (response.body && typeof response.body.getReader === "function") {
    //         // 获取响应数据流
    //         const reader = response.body.getReader();
    //         // 定义处理数据流的函数
    //         const processStream = async () => {
    //           let { done, value } = await reader.read();

    //           while (!done) {
    //             console.log('v----value', value)
    //             // 处理接收到的数据块
    //             const data = new TextDecoder().decode(value);
    //             console.log("看看初始数据===>", data);
    //             // if(that.isEND){
    //             //     this.str_list += data
    //             //     console.log("看看整理后的",this.str_list)
    //             //   }

    //             // 需要判断 数据中存有data: 并且后面有两个空格存在才会走这个处理方法
    //             if (data.includes("data: ")) {
    //               this.parseDataString(data);
    //               // let val = data.split("data: ")[1];
    //             } else {
    //               console.log("----看看这个",that.isEND);

    //               if (that.isEND) {
    //                   that.str_list += data
    //                   console.log("看看整理后的",this.str_list)
    //                 try {
    //                   console.log("延迟看看附件", JSON.parse(that.str_list));
    //                   this.messageList[this.messageList.length - 1].source_list = JSON.parse(that.str_list).source_list;
    //                 } catch {
    //                 // return;
    //                 }
    //               }
    //             }
    //             // 读取下一个数据块
    //             ({ done, value } = await reader.read());

    //             that.scrollBottom();
    //           }
    //           console.log(result.message, "看看消息记录");
    //           that.sessionStart({
    //             id: this.sessionId,
    //             message: this.messageList,
    //           });
    //         };
    //         // 启动处理数据流
    //         processStream();
    //         that.$forceUpdate();
    //         // 滚动到底部
    //         that.$nextTick(() => {
    //           that.scrollBottom();
    //         });
    //       } else {
    //         // 处理非流式响应
    //         console.log("Response is not a stream:", response);
    //       }
    //     })
    //     .catch((error) => {
    //       console.error("Error:", error);
    //     });
    // },
    qaFn(value) {
      let that = this;
      const result = that.sessionList.find(S => S.id == that.sessionId);
      
      // 新增：流式读取状态跟踪
      const streamState = {
        buffer: '',
        partialMessage: false
      };

      fetch(`${uni.$config.baseUrl}/kms-core-svc/qa`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "token": uni.getStorageSync("token")
        },
        body: JSON.stringify({
          user_input: value,
          chat_type: this.checked ? "raw" : "rag",
          sessionId: this.sessionId,
          history: result?.message || [],
        }),
      }).then(async (response) => {
        if (!response.body) throw new Error('No response body');
        
        const reader = response.body.getReader();
        const decoder = new TextDecoder('utf-8');
        
        // 使用递归处理流式数据
        const processChunk = async () => {
          const { done, value } = await reader.read();
          if (done) {
            // 处理最后可能残留的数据
            if (streamState.buffer.length > 0) {
              that.parseDataString(streamState.buffer);
            }
            // 保存会话
            that.sessionStart({
              id: that.sessionId,
              message: that.messageList,
            });
            return;
          }

          // 分块解码（处理可能的中文字符截断）
          const chunk = decoder.decode(value, { stream: true });
          streamState.buffer += chunk;

          // 特殊处理：检查缓冲区末尾是否是截断的JSON
          const processBuffer = () => {
            let startPos = 0;
            while (true) {
              const dataPos = streamState.buffer.indexOf('data: ', startPos);
              if (dataPos === -1) break;

              const endPos = streamState.buffer.indexOf('\n', dataPos);
              if (endPos === -1) {
                // 不完整消息，保留在缓冲区
                streamState.buffer = streamState.buffer.slice(dataPos);
                return;
              }

              // 提取完整消息
              const message = streamState.buffer.slice(dataPos + 6, endPos);
              try {
                const parsed = JSON.parse(message);
                // 直接更新消息列表（避免parseDataString的二次处理）
                const lastMsg = that.messageList[that.messageList.length - 1];
                if (parsed.content) lastMsg.content = (lastMsg.content || '') + parsed.content;
                if (parsed.source_list) lastMsg.source_list = parsed.source_list;
              } catch (e) {
                console.warn('JSON解析失败，尝试修复:', e);
                // 尝试修复后重新处理
                streamState.buffer = streamState.buffer.slice(dataPos);
                return;
              }

              startPos = endPos + 1;
            }
            // 清理已处理的数据
            streamState.buffer = startPos < streamState.buffer.length 
              ? streamState.buffer.slice(startPos) 
              : '';
          };

          processBuffer();
          that.scrollBottom();
          return processChunk(); // 递归处理下一块
        };

        await processChunk();
        that.$nextTick(() => {
          that.scrollBottom();
        });
      }).catch(error => {
        console.error('请求失败:', error);
        that.$refs.uToast.show({
          type: 'error',
          message: '请求处理失败'
        });
      });
    },
    parseDataString(dataString) {
		let that = this;
      dataString
        .split("data: ")
        .filter((item) => item !== "")
        .map((item) => {
          let str = item
          try {
            if (item.includes('content')) {
              str = JSON.parse(item).content
            }
          } catch (error) {
            console.log('JSON解析错误：', error);
          }
          // const str = item.replace(/\n\n/, "");
          console.log("ffff=====>", str, item);

          if (item.includes("context_text")) {
            console.log("这个是附件实例",item)
            // that.str_list += item
            // that.isEND = true;
            // console.log("看看这个实例========》》》",JSON.parse(item))
            try {
              console.log("延迟看看附件", JSON.parse(item));
              this.str_list += item
              this.messageList[this.messageList.length - 1].source_list = JSON.parse(item).source_list;
            } catch {
              return;
            }
          } else {
            if (str.includes("---end---")) {
              return;
            }
            const message = this.messageList[this.messageList.length - 1].content + str;
            this.messageList[this.messageList.length - 1].content = message;
          }
        });

      console.log("结尾打印====>", dataString);
    },
    sendFn() {
      let that = this;
      if (!this.val) {
        this.$refs.uToast.show({
          type: "default",
          message: "输入内容不能为空",
        });
        return;
      }
      if (!this.sessionId) {
        uni.setStorageSync("sessionIndex", 0);
        // let sessionList = uni.getStorageSync('sessionList') ? uni.getStorageSync('sessionList') : []
        const message = {
          name: this.val,
          message: [],
          date: this.dateFn(),
          id: uni.$guid(),
        };
        this.sessionId = message.id;
        this.sessionList.unshift(message);
        // uni.setStorageSync('sessionList', sessionList)
        this.sessionStart(message);
      }
      this.messageList.push(
        {
          name: "张三",
          id: 1001,
          photo: "https://cdn.uviewui.com/uview/album/1.jpg",
          content: this.val,
        },
        {
          name: "AI机器人",
          id: 1002,
          photo: "https://cdn.uviewui.com/uview/album/1.jpg",
          content: "",
          source_list: [],
          chat_type: this.checked ? "raw" : "rag",
        }
      );

      this.qaFn(this.val);
      setTimeout(() => {
        this.val = "";
        that.scrollBottom();
      }, 100);
    },
    scrollBottom() {
      // console.log("看看调用的问题",this.scrollTop)
      this.$nextTick(() => {
        this.scrollTop = this.scrollTop + 9999;
      });
    },
    qaTypeFn(status) {
      this.checked = !this.checked;
    },
  },
};
</script>

<style lang="scss" scoped>
::v-deep .uaMarkdownClass {
  background: #ffffff;
  padding: 20rpx;
  font-size: 28rpx;
  line-height: 2;
}
::v-deep .markdown-preview {
  padding: 10px !important;
  border-radius: 10rpx;

  code {
    max-width: 100%;
    word-break: break-word;
  }

  p {
    margin-bottom: 0;
    line-height: 60rpx;
  }
}

.container {
  width: 100%;
  height: 100%;

  .message_model {
    // height: 85vh;
    // overflow-y: auto;

    .message {
      display: flex;
      padding: 20rpx;
      box-sizing: border-box;
      font-size: 28rpx;

      .message_content {
        margin: 0 20rpx;
        display: flex;
        flex-direction: column;
        max-width: calc(100% - 80rpx);
      }

      .image {
        width: 60rpx;
        height: 60rpx;
        min-width: 60rpx;
        max-width: 60rpx;
        border-radius: 10rpx;
      }

      .content {
        // width: 80vw;
        width: auto;
        max-width: 80vw;
        padding: 20rpx 20rpx;
        line-height: 45rpx;
        background: #eee;
        border-radius: 10rpx;
        word-wrap: break-word;
        /* 允许在长单词内部换行 */
        word-break: break-all;
      }

      .self {
        background: #0084ff;
        color: white;
      }
    }
  }

  .fileList {
    // display: flex;
    // align-items: center;
    width: 100%;
    padding: 10rpx 10rpx;
    line-height: 45rpx;
    background: white;
    border-radius: 5rpx;
    margin-top: 20rpx;
    font-size: 30rpx;

    .title {
      font-size: 32rpx;
      font-weight: 550;
      padding: 30rpx 30rpx 15rpx;
    }

    .view_list {
      width: 80vw;
      padding: 10rpx;

      .file {
        background: white;
        margin: 10rpx;
        border-radius: 5rpx;
        padding: 5rpx 10rpx;
        color: #1c2126;
      }
    }
  }

  .sendMessage {
    position: fixed;
    bottom: 0rpx;
    width: 100%;
    display: flex;
    align-items: center;
    padding: 20rpx;
    gap: 20rpx;
    background: white;

    .textarea {
      width: 70vw;
      min-height: 80rpx;
      border: none !important;
    }

    .btn {
      width: 60rpx;
      height: 60rpx;
      margin-bottom: 12rpx;
    }
  }
}

.qaType {
  position: fixed;
  top: 20rpx;
  right: 20rpx;
  z-index: 99999;
}

.qaType_text {
  position: fixed;
  top: 18rpx;
  right: 20rpx;
  z-index: 99999;
  width: 260rpx;
  height: 48rpx;
  border-radius: 30rpx;
  background: #f5f7fb;
  line-height: 48rpx;
  font-size: 24rpx;

  text {
    width: 50%;
    border-radius: 30rpx;
    display: inline-block;
    text-align: center;
  }

  .select {
    background: #319bfe;
    color: white;
  }
}

::v-deep .uni-textarea-wrapper {
  height: 40rpx !important;
}
::v-deep uni-scroll-view {
  height: 82vh !important;
}
::v-deep .markdown-preview ul li {
  font-size: 30rpx !important;
  line-height: 48rpx !important;
}
::v-deep .markdown-preview p {
  font-size: 30rpx !important;
}
</style>
